package net.freebytes.test;



import java.util.List;


public class BytesOps implements HexConvert {

	public int length(byte[] bytes) {
		return isEmpty(bytes) ? 0 : bytes.length;
	}

	public byte[] trim(byte[] bytes, int elementsForward, int elementsBackward) {
		if (!verifyFB(bytes, elementsForward, elementsBackward)) {
			return new byte[0];
		}
		int subLen = bytes.length - elementsForward - elementsBackward;
		byte[] sub = new byte[subLen];
		try {
			System.arraycopy(bytes, elementsForward, sub, 0, subLen);
		} catch (Exception e) {
		}
		return sub;
	}

	private boolean verifyFB(byte[] bytes, int elementsForward,
			int elementsBackward) {
		if (isEmpty(bytes)
				|| (elementsForward + elementsBackward) >= bytes.length
				|| elementsForward < 0 || elementsBackward < 0) {
			return false;
		}
		return true;
	}

	public byte getByte(byte[] bytes, int pos) {
		try {
			if (pos >= bytes.length || pos < 0) {
				throw new RuntimeException("pos should be :0-"
						+ (bytes.length - 1));
			}
		} catch (Exception e) {
		}
		return bytes[pos];
	}

	public int getAscII(byte[] bytes, int pos) {
		return (int) getByte(bytes, pos);
	}

	public String toString(byte[] bytes, int start, int end) {
		if (!verifySE(bytes, start, end)) {
			return new String();
		}
		StringBuffer s = new StringBuffer();
		for (int i = start; i < end; i++) {
			s.append((char) getByte(bytes, i));
		}
		return s.toString();
	}

	private boolean verifySE(byte[] bytes, int start, int end) {
		if (isEmpty(bytes) || start >= end || start < 0 || end > bytes.length) {
			return false;
		}
		return true;
	}

	public String toString(byte[] bytes) {
		if (isEmpty(bytes)) {
			return new String();
		}
		return toString(bytes, 0, bytes.length);
	}

	public String toHexString(byte[] bytes) {
		if (isEmpty(bytes)) {
			return new String();
		}
		return HEXCONV.toHexString(bytes);
	}

	public byte[] replaceAll(byte[] bytes, byte[] former, byte[] latter) {
		if (isEmpty(bytes)) {
			return new byte[0];
		}
		if (!isEmpty(former) && bytes.length >= former.length) {
			return arrayReplace(bytes, former, latter, 0);
		}
		return bytes;
	}

	public int indexOf(byte[] bytes, byte[] subbytes, int startIndex) {
		if (isEmpty(subbytes)) {
			return 0;
		}
		if (bytes == null || bytes.length < subbytes.length) {
			return -1;
		}
		KmpMatcher kmpMatcher = new KmpMatcher();
		kmpMatcher.computeFailure4Byte(subbytes);
		return kmpMatcher.indexOf(bytes, startIndex);
	}

	public int findFirst(byte[] bytes, byte[] subbytes) {
		return indexOf(bytes, subbytes, 0);
	}

	public boolean startWith(byte[] bytes, byte[] start) {
		if (isEmpty(start)) {
			return true;
		}
		if (bytes == null || bytes.length < start.length) {
			return false;
		}
		for (int i = 0; i < start.length; i++) {
			if (start[i] != bytes[i]) {
				return false;
			}
		}
		return true;
	}

	public boolean endWith(byte[] bytes, byte[] end) {
		if (isEmpty(end)) {
			return true;
		}
		if (bytes == null || bytes.length < end.length) {
			return false;
		}
		int startPos = bytes.length - end.length;
		for (int i = 0; i < end.length; i++) {
			if (end[i] != bytes[startPos + i]) {
				return false;
			}
		}
		return true;
	}

	protected boolean isEmpty(byte[] bytes) {
		return bytes == null || bytes.length == 0;
	}

	private byte[] arrayReplace(byte[] bytes, byte[] former, byte[] latter,
			int startIndex) {
		int index = indexOf(bytes, former, startIndex);
		if (index != -1) {
			int newLength = bytes.length + latter.length - former.length;
			byte[] newBytes = new byte[newLength];
			try {
				System.arraycopy(bytes, 0, newBytes, 0, index);
				System.arraycopy(latter, 0, newBytes, index, latter.length);
				System.arraycopy(bytes, index + former.length, newBytes, index
						+ latter.length, bytes.length - index - former.length);
				int newStart = index + latter.length;
				if ((newBytes.length - newStart) > latter.length) {
					return arrayReplace(newBytes, former, latter, newStart);
				}
			} catch (Exception e) {
			}
			return newBytes;
		}
		return bytes;
	}

	public byte[] connect(byte[] byteArray1, byte[] byteArray2) {
		if (isEmpty(byteArray1)) {
			return byteArray2;
		}
		if (isEmpty(byteArray2)) {
			return byteArray1;
		}
		byte[] result = new byte[byteArray1.length + byteArray2.length];
		try {
			System.arraycopy(byteArray1, 0, result, 0, byteArray1.length);
			System.arraycopy(byteArray2, 0, result, byteArray1.length,
					byteArray2.length);
		} catch (Exception e) {
		}
		return result;
	}

	public byte[] connect(List<byte[]> byteArrayList) {
		byte[] result = null;
		if (byteArrayList != null) {
			for (byte[] bytes : byteArrayList) {
				result = connect(result, bytes);
			}
		}
		return result;

	}

	public byte[] getSubArray(byte[] bytes, int start, int end) {
		if (!verifySE(bytes, start, end)) {
			return new byte[0];
		}
		byte[] subBytes = new byte[end - start];
		for (int i = 0; i < end - start; i++) {
			subBytes[i] = bytes[start + i];
		}
		return subBytes;
	}

}
